<template>
    <div class="box">
        <div class="box1">
            <span>商品基础信息</span>
            <el-button type="danger" style="float: right;margin-right: 20px;margin-top: 10px;" @click="add">创建</el-button>
            <el-button type="info" style="float: right;margin-right: 20px;margin-top: 10px;">取消</el-button>
        </div>
        <div class="box2">
            <el-form :model="form" label-width="120px">
                <el-form-item label="商品名称">
                    <el-input v-model="form.name" width="100px" placeholder="请输入商品名称" />
                </el-form-item>
                <el-form-item label="商品描述">
                    <el-input v-model="form.context" placeholder="请输入商品描述" />
                </el-form-item>
                <el-form-item label="商品分类">
                    <el-select v-model="form.cate" placeholder="请选择商品类型">
                        <el-option label="全部" value="" />
                        <el-option v-for="(item, idx) in cate" :key="item" :label="item.name" :value="item._id" />
                    </el-select>
                </el-form-item>
                <el-form-item label="商品原价">
                    <el-input v-model="form.old_price" placeholder="请输入商品原价" />
                </el-form-item>
                <el-form-item label="商品销售价">
                    <el-input v-model="form.price" placeholder="请输入商品销售价" />
                </el-form-item>
                <el-form-item label="商品销量">
                    <el-input v-model="form.sales" placeholder="请输入商品销量" />
                </el-form-item>
                <el-form-item label="商品库存">
                    <el-input v-model="form.num" placeholder="请输入商品库存" />
                </el-form-item>
            </el-form>
            <div class="box3">
                <span>商品展示</span>
                <input type="file" @change="handleFileChange" style="margin-left: 13px;"/> <!-- 限制只能选择视频文件 -->
                <el-button type="primary" @click="upload">开始上传</el-button>
            </div>
        </div>
    </div>
</template>

<script setup lang="ts">
import { reactive, ref ,defineComponent,onMounted} from 'vue'
import axios from 'axios';
import CryptoJS from 'crypto-js';
import router from '@/router';
const form = reactive({
    name: '',
    region: '',
    price: '',
    context: '',
    sales: "",
    cate: "",
    old_price: "",
    appraise: "",
    video: "",
    num:"",
})
const cate = ref([])

const getcate = async() => {
    const {data} =await axios.get('http://localhost:3000/jsb/getcate')
    cate.value = data.list
}

onMounted(() => {
    getcate()
})
const add = async()=>{
    const {data} = await axios.post('http://localhost:3000/jsb/addlist',form)
    console.log('====================================');
    console.log(data);
    console.log('====================================');
    router.push('/index/shoplist')
}
const file = ref<File | null>(null); // 存储选中的文件
        const progress = ref<number>(0); // 上传进度
        const uploadedChunks = ref<string[]>([]); // 已上传的分片索引
        // 当文件选择改变时触发
        const handleFileChange = (event: Event) => {
            const target = event.target as HTMLInputElement;// 获取文件对象
            if (target.files && target.files.length > 0) {
                file.value = target.files[0];
                // 清除已上传的分片记录
                uploadedChunks.value = [];
            }
        };

        // 分片函数，将文件切分为多个小块
        const createFileChunk = (file: File, size = 1 * 1024 * 1024): File[] => {// 1MB
            const chunks: File[] = [];// 存储分片后的文件
            let cur = 0;
            while (cur < file.size) {
                chunks.push(file.slice(cur, cur + size));// 将文件切分为多个小块
                cur += size;
            }
            return chunks;
        };

        // 计算文件的校验和
        const calculateChecksum = (file: File): Promise<string> => {// 计算文件的校验和
            return new Promise((resolve, reject) => {// 创建一个Promise对象
                const fileReader = new FileReader();// 创建一个FileReader对象
                fileReader.onload = (event) => {// 当文件读取完成时触发
                    const arrayBuffer = event.target?.result as ArrayBuffer;// 获取文件的ArrayBuffer
                    const wordArray = CryptoJS.lib.WordArray.create(new Uint8Array(arrayBuffer));// 将ArrayBuffer转换为WordArray
                    const hash = CryptoJS.MD5(wordArray).toString();// 计算文件的MD5值
                    resolve(hash);
                };
                fileReader.onerror = (error) => {// 当文件读取出错时触发
                    reject(error);// 返回错误信息
                };
                fileReader.readAsArrayBuffer(file);// 将文件读取为ArrayBuffer
            });
        };



        // 检查分片是否已上传
        const isChunkUploaded = (index: number): boolean => {
            return uploadedChunks.value.includes(index.toString());// 检查分片是否已上传
        };

        // 记录已上传的分片
        const markChunkAsUploaded = (index: number) => {
            if (!uploadedChunks.value.includes(index.toString())) {
                uploadedChunks.value.push(index.toString());// 将分片索引添加到已上传的分片列表中
            }
        };

        // 开始上传
        const upload = async () => {
            if (!file.value) return;
            // 计算文件的校验和
            const originalChecksum = await calculateChecksum(file.value);
            console.log(`原始文件校验和: ${originalChecksum}`);

            // 查询已上传的分片
            try {
                const response = await axios.get('http://localhost:3000/jsb/uploaded-chunks', {
                    params: {
                        fileName: encodeURIComponent(file.value.name)// 对文件名进行编码
                    }// 发送文件名作为查询参数
                });
                uploadedChunks.value = response.data;// 将已上传的分片列表赋值给uploadedChunks
            } catch (error) {
                console.error('查询已上传分片失败:', error);
                return;
            }
            // 创建分片
            const chunks = createFileChunk(file.value);
            for (let i = 0; i < chunks.length; i++) {
                if (isChunkUploaded(i)) {
                    console.log(`分片 ${i} 已上传，跳过`);
                    continue;
                }
                try {
                    await axios.post('http://localhost:3000/jsb/upload', chunks[i], {
                        onUploadProgress: (e) => {
                            // 计算当前上传进度
                            progress.value = ((i + e.loaded / e.total) / chunks.length) * 100;
                        },
                        headers: {
                            'Content-Type': 'application/octet-stream',// 设置请求头为二进制流
                            'File-Name': encodeURIComponent(file.value.name), // 对文件名进行编码
                            'File-Index': i.toString(),// 分片索引
                            'Total-Chunks': chunks.length.toString()// 分片总数
                        }
                    });
                    markChunkAsUploaded(i); // 标记分片为已上传
                } catch (error) {
                    console.error('上传失败:', error);
                    break;
                }
            }

            // 所有分片上传完成后，通知服务器合并文件
            if (progress.value === 100) {
                try {
                    await axios.post('http://localhost:3000/jsb/merge', {
                        fileName: encodeURIComponent(file.value.name), // 对文件名进行编码
                        totalChunks: chunks.length,// 分片总数
                        originalChecksum: originalChecksum // 发送原始文件校验和
                    });
                    console.log('文件合并完成');
                } catch (error) {
                    console.log(file.value.name, '文件分片');
                    console.error('文件合并失败:', error);
                }
            }
        };
</script>

<style lang="scss" scoped>
.box {
    width: 80%;
    height: 100%;
    background-color: #fff;
    margin-left: 20px;
    margin-top: 20px;
}

.box1 {
    width: 100%;
    height: 50px;
    border-bottom: 1px solid #ccc;
    line-height: 50px;

    span {
        margin-left: 20px;
    }
}

.box3 {
    width: 100%;
    height: 50px;
    line-height: 50px;
    span {
        margin-left: 60px;
    }
}

.box2 {
    width: 100%;
    height: 100%;
    margin-top: 20px;

    .el-form {
        width: 40%;
        margin-left: 20px;
    }
}
</style>